package com.blog.config;

import com.blog.security.JwtAuthenticationFilter;
import com.blog.security.JwtAuthenticationProvider;
import com.blog.security.UserDetailsServiceImpl;
import com.blog.util.JwtUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final JwtAuthenticationProvider jwtAuthenticationProvider;
    private final JwtUtil jwtUtil;
    private final UserDetailsServiceImpl userDetailsService;

    public SecurityConfig(JwtAuthenticationProvider jwtAuthenticationProvider,
                         JwtUtil jwtUtil,
                         UserDetailsServiceImpl userDetailsService) {
        this.jwtAuthenticationProvider = jwtAuthenticationProvider;
        this.jwtUtil = jwtUtil;
        this.userDetailsService = userDetailsService;
    }

    @Bean
    public JwtAuthenticationFilter jwtAuthenticationFilter() {
        return new JwtAuthenticationFilter(jwtUtil, userDetailsService);
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .cors().and()
            .csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
            // 公开访问的端点
            .antMatchers("/api/auth/**").permitAll()
            // 文章和分类的公开访问
            .antMatchers("/api/articles/list").permitAll()
            .antMatchers("/api/articles/{id}").permitAll()
            .antMatchers("/api/categories").permitAll()
            .antMatchers("/api/comments/article/**").permitAll()
            .antMatchers("/api/comments/{id}").permitAll()
            // 需要认证的端点 - 普通用户和管理员都可以访问
            .antMatchers("/api/articles/manage").hasAnyRole("USER", "ADMIN")
            .antMatchers("/api/articles").hasAnyRole("USER", "ADMIN")
            .antMatchers("/api/comments").hasAnyRole("USER", "ADMIN")
            // 管理员专用端点
            .antMatchers("/api/users/**").hasRole("ADMIN")
            .antMatchers("/api/articles/dashboard").hasRole("ADMIN")
            .antMatchers("/api/categories/**").hasRole("ADMIN")
            .antMatchers("/api/admin/**").hasRole("ADMIN")
            // 其他请求需要认证
            .anyRequest().authenticated()
            .and()
            .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(jwtAuthenticationProvider);
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOriginPatterns(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH", "HEAD"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setAllowCredentials(true);
        configuration.setExposedHeaders(Arrays.asList("*"));
        configuration.setMaxAge(3600L);
        
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
} 